package com.lrkj.payfee.service.impl;

import cn.hutool.core.date.DateUtil;
import com.lrkj.common.constant.FeeConstants;
import com.lrkj.common.utils.DateUtils;
import com.lrkj.common.utils.uuid.IdUtils;
import com.lrkj.framework.security.MiniContextUtils;
import com.lrkj.framework.utils.NumberUtils;
import com.lrkj.framework.utils.SerialNumUtil;
import com.lrkj.payfee.domain.*;
import com.lrkj.payfee.domain.vo.PayFeeVo;
import com.lrkj.payfee.factory.PayFeeFactory;
import com.lrkj.payfee.service.*;
import com.lrkj.payfee.vo.BillPaymentVo;
import com.lrkj.payfee.vo.BillVo;
import com.lrkj.payfee.vo.NormChargeVo;
import com.lrkj.property.domain.Room;
import com.lrkj.property.service.IRoomService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;


//物业费用缴费逻辑处理
@Service
public class WxPayfeeServiceImpl implements IWxPayfeeService {


    @Autowired
    private IRoomService roomService;

    @Autowired
    private IRoomNormService roomNormService;

    @Autowired
    private IRuleCostService ruleCostService;

    @Autowired
    private IReceiptDetailService receiptDetailService;

    @Autowired
    private IReceiptRecordService receiptRecordService;

    @Autowired
    private PayFeeFactory payFeeFactory;

    @Autowired
    private IReceiptService receiptService;

    @Autowired
    private IModePaymentService modePaymentService;

    @Autowired
    private IPayOrderService payOrderService;
    @Override
    @Transactional
    public int payment(BillPaymentVo billPaymentVo) {
        //支付订单
        PayOrder payOrder = this.createPayOrder(billPaymentVo);
        //房屋信息
        //房屋收费标准
        Map<String, NormChargeVo> roomNormMap = new HashMap<>();
        NormChargeVo eg = new NormChargeVo();
        eg.setStatus(FeeConstants.room_norm_status_10001);
        eg.setRoomId(billPaymentVo.getRoomId());
        List<NormChargeVo> roomNorms = roomNormService.selectArrearageRoomNorm(eg);
        roomNorms.stream().forEach(x -> {
            roomNormMap.put(x.getRoomId() + x.getNormId(), x);
        });
        List<Receipt> savaReceipts = new ArrayList<>();
        List<ModePayment> savaModePayments = new ArrayList<>();
        billPaymentVo.getBillVos().stream().forEach(x -> {
            if (null != x.getCostIds() && x.getCostIds().size() > 0) {
                List<RuleCost> ruleCosts = ruleCostService.selectRuleCostIds(x.getCostIds());
                //创建收款单
                Receipt receipt = this.createReceipt(billPaymentVo.getRoom(), x);
                receipt.setPayOrderId(payOrder.getId());
                //创建收款单明细
                this.createReceiptDetail(receipt, ruleCosts);
                //创建收款方式
                ModePayment modePayment = this.createModePayment(receipt);
                //更新收费标准
                this.updateRoomNorm(receipt, roomNormMap);
                savaReceipts.add(receipt);
                savaModePayments.add(modePayment);
            }
        });
        //批量新增收款单信息
        receiptService.doSaveList(savaReceipts);
        //批量新增付款方式
        modePaymentService.doSaveList(savaModePayments);
        return 1;
    }

    /***
     * 创建收款单
     *
     * ***/
    private Receipt createReceipt(Room room, BillVo billVo) {
        Receipt receipt = new Receipt();
        receipt.setReceiptId(IdUtils.simpleUUID());
        receipt.setNo(this.getNo(FeeConstants.receipt_key));
        receipt.setRoomId(room.getId());
        receipt.setOwnerId(room.getOwnerId());
        receipt.setBillDate(DateUtils.getNowDate());
//        receipt.setBillUser(user.getNickName());
//        receipt.setBillUserCode(user.getUserName());
        receipt.setAuditStatus(FeeConstants.audit_status_10001);
        receipt.setInvoiceStatus(FeeConstants.invoice_status_10001);
        receipt.setCreateBy("admin");
        receipt.setCreateTime(DateUtils.getNowDate());
        receipt.setBillDate(DateUtils.getNowDate());
        receipt.setReceivableMoney(billVo.getAmountOwed());//应收金额
        receipt.setBillMoney(billVo.getAmountOwed());//实收金额
        receipt.setOddChangeMoney(new BigDecimal(0));//找零
        receipt.setTransferAmount(new BigDecimal(0));//转存
        receipt.setAmountAmount(new BigDecimal(0));//冲抵
        receipt.setSpecialMoney(new BigDecimal(0));//优惠
        receipt.setOddChangeMoney(new BigDecimal(0));
        receipt.setOddChangeMoney(new BigDecimal(0));
        return receipt;
    }

    private void createReceiptDetail(Receipt receipt, List<RuleCost> ruleCosts) {
        List<ReceiptDetail> receiptDetails = new ArrayList<>();
        List<ReceiptRecord> savaReceiptRecords = new ArrayList<>();
        ruleCosts.stream().forEach(x -> {
            //为了以后扩展逻辑定义的
            List<RuleCost> savaRuleCosts = new ArrayList<>();

            ReceiptDetail detail = new ReceiptDetail();
            detail.setReceiptDetailId(IdUtils.simpleUUID());//收款单明细ID
            detail.setReceiptId(receipt.getReceiptId());//收款单ID
            detail.setRoomId(x.getRoomId());//房屋ID
            detail.setOwnerId(x.getOwnerId());//业主ID
            detail.setProjectId(x.getProjectId());//收费类型
            detail.setChargeId(x.getChargeId());//收费项目
            detail.setNormId(x.getNormId());//收费标准
            detail.setBeginTime(x.getBeginTime());//开始计费时间
            detail.setFinishTime(x.getFinishTime());//结束计费时间
            detail.setPrices(x.getPrices());//单价
            detail.setReceivableMoney(x.getAmountOwed());//应收金额
            detail.setAmountAmount(new BigDecimal(0));//欠费金额
            detail.setBillMoney(x.getAmountOwed());//实收金额
            detail.setSpecialMoney(new BigDecimal(0));//优惠金额
            detail.setQueenMoney(new BigDecimal(0));//优惠后金额
            detail.setStatus(FeeConstants.receipt_detail_status_10);//收款明细状态 --- 已收款
            detail.setCreateTime(DateUtils.getNowDate());
            detail.setPaymentCycle(DateUtils.dateTime(receipt.getBillDate()));
            detail.setRefundAmount(x.getAmountOwed());//剩余可退款金额
            detail.setDrawbackMoney(new BigDecimal(0));//退款金额
//            detail.setCreateBy(user.getNickName());
            receiptDetails.add(detail);
            //费用明细欠费信息,变更
            x.setAmountOwed(new BigDecimal(0));//欠费金额
            x.setStatus(FeeConstants.charge_status_10002); //已收全
            x.setFullReceiptDate(receipt.getBillDate());
            savaRuleCosts.add(x);
            //缴费明细记录
            savaReceiptRecords.add(this.createRuleCostDetail(receipt.getReceiptId(), detail.getReceiptDetailId(), x));
            detail.setRuleCosts(savaRuleCosts);

        });
        //更新费用单欠费金额
        ruleCostService.updateAmountOwed(ruleCosts);
        //批量创建收费明细
        this.receiptDetailService.doSaveList(receiptDetails);
        //批量创建费用单 缴费记录
        this.receiptRecordService.doSaveList(savaReceiptRecords);
        receipt.setReceiptDetails(receiptDetails);
    }

    //创建付款方式
    private ModePayment createModePayment(Receipt receipt) {
        ModePayment modePayment = new ModePayment();
        modePayment.setModePaymentId(IdUtils.simpleUUID());
        modePayment.setReceiptId(receipt.getReceiptId());//收款单ID
        modePayment.setBillMoney(receipt.getBillMoney());
        modePayment.setCollectionMethod(FeeConstants.collection_method_WX);//微信支付
        return modePayment;
    }


    //创建费用单收费记录
    private ReceiptRecord createRuleCostDetail(String receiptId, String detailId, RuleCost costs) {
        ReceiptRecord record = new ReceiptRecord();
        record.setReceiptRecordId(IdUtils.simpleUUID());
        record.setReceiptId(receiptId);//收款单ID;
        record.setReceiptDetailId(detailId);//收款明细ID
        record.setCostId(costs.getCostId());//费用单明细ID
        record.setReceivableMoney(costs.getReceivableMoney());//应收金额
        record.setBillMoney(costs.getPaidMoney());//实收金额
        record.setSpecialMoney(costs.getSpecialMoney());//优惠金额
        record.setAmountAmount(costs.getAmountAmount());//冲抵金额
        record.setCreateTime(DateUtils.getNowDate());
        record.setPaymentNote(costs.getPaymentNote());
        record.setAmountOwed(costs.getAmountOwed());//欠费金额
        return record;
    }

    /*
     * 更新房屋收费标准
     * **/
    private void updateRoomNorm(Receipt receipt, Map<String, NormChargeVo> roomNormMap) {
        receipt.getReceiptDetails().stream().forEach(x -> {
            //临时收费项目不更新房屋收费标准
            if (!x.getProjectId().equals(FeeConstants.charge_project_03)) {
                List<RoomNorm> updateRoomNormList = new ArrayList<>();
                if (null != x.getRuleCosts() && x.getRuleCosts().size() > 0) {
                    //升序
                    Collections.sort(x.getRuleCosts(), new Comparator<RuleCost>() {
                        @Override
                        public int compare(RuleCost o1, RuleCost o2) {
                            return o1.getFinishTime().compareTo(o2.getFinishTime());
                        }
                    });

                    String key = x.getRoomId() + x.getNormId();
                    //房屋收费标准
                    NormChargeVo oldRoomNorm = roomNormMap.get(key);
                    RuleCost ruleCost = x.getRuleCosts().get(x.getRuleCosts().size() - 1);
                    //如果是未收全的单子
                    if (ruleCost.getStatus().equals(FeeConstants.charge_status_10001)) {
                        if (x.getRuleCosts().size() > 1) {
                            ruleCost = x.getRuleCosts().get(x.getRuleCosts().size() - 2);
                        } else {
                            ruleCost = null;
                        }
                    }
                    if (null != ruleCost) {
                        oldRoomNorm.setNextBeginChargeTime(ruleCost.getBeginTime());
                        oldRoomNorm.setNextFinishChargetime(ruleCost.getFinishTime());
                        RoomNorm updateBean = new RoomNorm();
                        //暂时   只有常规收费项目  更新下一次计费时间
                        PayFeeVo payFeeVo = payFeeFactory.getPayFeeVo(oldRoomNorm);
                        updateBean.setRoomNormId(oldRoomNorm.getRoomNormId());
                        updateBean.setStatus(payFeeVo.getStatus());
                        if (x.getProjectId().equals(FeeConstants.charge_project_01)) {
                            updateBean.setNextBeginChargeTime(payFeeVo.getBeginTime());
                            updateBean.setNextFinishChargetime(payFeeVo.getFinishTime());
                            updateBean.setReceivableTime(payFeeVo.getReceivableTime());
                        }
                        //交讫年月
                        updateBean.setDeliveryTime(x.getRuleCosts().get(x.getRuleCosts().size() - 1).getFinishTime());
                        updateRoomNormList.add(updateBean);
                        roomNormService.updateByBatch(updateRoomNormList);
                    }
                }
            }
        });
    }

    //创建支付订单
    private PayOrder createPayOrder(BillPaymentVo billPaymentVo) {
        PayOrder payOrder = new PayOrder();
        payOrder.setId(IdUtils.simpleUUID());
        payOrder.setRoomId(billPaymentVo.getRoomId());
        payOrder.setSerialNo(billPaymentVo.getSerialNo());
        payOrder.setOrderNo(billPaymentVo.getOrderNo());
        payOrder.setPayMoney(billPaymentVo.getPayMoney());
        payOrder.setCreateBy(MiniContextUtils.getPhoneNum());
        payOrder.setCreateTime(DateUtil.parse(billPaymentVo.getPaymentTime(), DateUtils.YYYY_MM_DD_HH_MM_SS));
        payOrder.setOrderType(FeeConstants.ORDER_TYPE_WX);//微信支付
        payOrderService.insertPayOrder(payOrder);
        return payOrder;
    }


    public String getNo(String key) {
        int nextVal = SerialNumUtil.getInstance().nextInt(key);
        return key + NumberUtils.frontCompWithZore(nextVal, 7);
    }

}
